package com.example.teesystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.teesystem.common.cache.CourseCache;
import com.example.teesystem.common.cache.UserCache;
import com.example.teesystem.common.exception.CustomException;
import com.example.teesystem.common.utils.PermissionUtil;
import com.example.teesystem.common.utils.Response;
import com.example.teesystem.common.utils.ResultCode;
import com.example.teesystem.entity.Assistant;
import com.example.teesystem.entity.Course;
import com.example.teesystem.entity.Permission;
import com.example.teesystem.entity.vo.assistant.AssistantUpdateVo;
import com.example.teesystem.entity.vo.assistant.AssistantUploadVo;
import com.example.teesystem.filter.MyHandlerInterceptor;
import com.example.teesystem.mapper.AssistantMapper;
import com.example.teesystem.service.AssistantService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class AssistantServiceImpl extends ServiceImpl<AssistantMapper,Assistant>
    implements AssistantService {
    private final AssistantMapper assistantMapper;

    private final Integer NUM = 8;

    /**
     * 增加助教
     * @param assistantUploadVo
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Response add(AssistantUploadVo assistantUploadVo){
        Assistant assistant = new Assistant();
        Integer courseId = assistantUploadVo.getCourseId();
        Integer num = this.getAssistantByCourse(courseId).size();
        if(num >= NUM){
            return Response.error(ResultCode.ASSISTANT_COUNT_LIMIT_ERROR.getMsg(), ResultCode.ASSISTANT_COUNT_LIMIT_ERROR.getCode());
        }
        if(!this.selectByCourseAndAssistant(assistantUploadVo).isEmpty()){
            return Response.error(ResultCode.ASSISTANT_EXIST_ERROR.getMsg(),ResultCode.ASSISTANT_EXIST_ERROR.getCode());
        }
        if(assistantUploadVo.getAssistantId() != MyHandlerInterceptor.getUid()){
            BeanUtils.copyProperties(assistantUploadVo,assistant);
            this.save(assistant);
            return Response.ok();
        }
        else {
            return Response.error(ResultCode.ASSISTANT_ADD_ERROR.getMsg(),ResultCode.ASSISTANT_ADD_ERROR.getCode());
        }
    }

    /**
     * 批量增加助教
     * @param assistantUploadVos
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)//回滚
    public Response add(List<AssistantUploadVo> assistantUploadVos){
        ArrayList<Assistant> assistants = new ArrayList<>();
        assistantUploadVos.forEach(assistantUploadVo -> {
            Assistant assistant = new Assistant();
            Integer courseId = assistantUploadVo.getCourseId();
            Integer num = this.getAssistantByCourse(courseId).size();
            if(num >= NUM){
                throw new CustomException(ResultCode.ASSISTANT_COUNT_LIMIT_ERROR.getMsg(), ResultCode.ASSISTANT_COUNT_LIMIT_ERROR.getCode());
            }
            if(!this.selectByCourseAndAssistant(assistantUploadVo).isEmpty()){
                throw new CustomException(ResultCode.ASSISTANT_EXIST_ERROR.getMsg(),ResultCode.ASSISTANT_EXIST_ERROR.getCode());
            }
            if(assistantUploadVo.getAssistantId() != MyHandlerInterceptor.getUid()){
            BeanUtils.copyProperties(assistantUploadVo,assistant);
            assistants.add(assistant);
            }
            else {
                throw new CustomException(ResultCode.ASSISTANT_ADD_SELF_ERROR.getMsg(), ResultCode.ASSISTANT_ADD_SELF_ERROR.getCode());
            }
        });
        this.saveBatch(assistants);
        return Response.ok();
    }

    /**
     * 更新助教信息
     * @param assistantUpdateVo
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Response update(AssistantUpdateVo assistantUpdateVo){
        Assistant assistant = new Assistant();
        BeanUtils.copyProperties(assistantUpdateVo, assistant);
        assistant.setId(assistantMapper.getAssistantId(assistantUpdateVo.getAssistantId(),assistantUpdateVo.getCourseId()));
        this.updateById(assistant);
        return Response.ok();
    }

    /**
     * 删除助教
     * @param id
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Response remove(Integer id){
        if(!this.removeById(id)){
            return Response.error(ResultCode.ASSISTANT_REMOVE_ERROR.getMsg(),ResultCode.ASSISTANT_REMOVE_ERROR.getCode());
        }
        return Response.ok();
    }

    /**
     * 根据课程号和用户号查询助教
     * @param assistantUploadVo
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public List<Assistant> selectByCourseAndAssistant(AssistantUploadVo assistantUploadVo){
        QueryWrapper<Assistant> wrapper = new QueryWrapper<>();
        wrapper.eq("course_id", assistantUploadVo.getCourseId())
                .eq("assistant_id", assistantUploadVo.getAssistantId());
        return this.list(wrapper);

    }

    /**
     * 根据课程Id获取助教
     * @param courseId
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public List<Assistant> getAssistantByCourse(Integer courseId){
        QueryWrapper<Assistant> wrapper = new QueryWrapper<>();
        wrapper.eq("course_id", courseId)
                .eq("is_delete", 0);
        List<Assistant> assistants = this.list(wrapper);
        return assistants;
    }

    /**
     * 根据assistantId取得所能管理的课程
     * @param assistantId
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public List<Course> getAssistantByAid(Integer assistantId){
        QueryWrapper<Assistant> wrapper = new QueryWrapper<>();
        wrapper.eq("assistant_id", assistantId);
        List<Assistant> assistants = this.list(wrapper);
        List<Course> courses = new ArrayList<>();
        for(Assistant assistant:assistants){
            courses.add(CourseCache.courseMap.get(assistant.getCourseId()));
        }
        return courses;
    }

    public List<Permission> getAssistantPermissions(Integer courseId, Integer assistantId){
        return PermissionUtil.getMyPermission(assistantMapper.getAssistantPermission(assistantId,courseId));
    }
    
    @Override
    public List<String> getAssistantNamesByCourseId(Integer courseId) {
        return this.baseMapper.selectAssistantIdByCourseId(courseId).stream()
                .map(id -> UserCache.userMap.getOrDefault(id, UserCache.NONE_USER).getMyName())
                .collect(Collectors.toList());
    }
    
}
